package com.jh.netty.server;

import com.jh.netty.ws.WebSocketHandler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketFrameAggregator;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolConfig;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.CharsetUtil;

import java.util.List;

/**
 * 协议初始化解码器.
 * <p>
 * 用来判定实际使用什么协议.</b>
 */
public class SocketChooseHandler extends ByteToMessageDecoder {

    /**
     * WebSocket握手的协议前缀
     */
    private static final String WEBSOCKET_PREFIX = "GET /";

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        String protocol = getBufStart(in);
        if (protocol.startsWith(WEBSOCKET_PREFIX)) {
            //  websocket连接时，执行以下处理
            // HttpServerCodec：将请求和应答消息解码为HTTP消息
            ctx.pipeline().addLast("http-codec", new HttpServerCodec());

            // HttpObjectAggregator：将HTTP消息的多个部分合成一条完整的HTTP消息
            ctx.pipeline().addLast("aggregator", new HttpObjectAggregator(65535));

            // ChunkedWriteHandler：向客户端发送HTML5文件,文件过大会将内存撑爆
            ctx.pipeline().addLast("http-chunked", new ChunkedWriteHandler());

            ctx.pipeline().addLast("WebSocketAggregator", new WebSocketFrameAggregator(65535));

            //  若超过80秒未收到约定心跳，则主动断开channel释放资源
//            ctx.pipeline().addLast(new IdleStateHandler(80,0,0));
//            ctx.pipeline().addLast(new NettyHeartKeeper(NettyHeartKeeper.TYPE_WEBSOCKET));

            WebSocketServerProtocolConfig conf = WebSocketServerProtocolConfig.newBuilder()
                    .websocketPath("/ws")
                    .checkStartsWith(true)
                    .build();
            //用于处理websocket, /ws为访问websocket时的uri
            ctx.pipeline().addLast("ProtocolHandler", new WebSocketServerProtocolHandler(conf));
            ctx.pipeline().addLast("socketHandler", new WebSocketHandler());
        } else {
            //  常规TCP连接时，执行以下处理
            // encoder 服务端 -> 客户端 编码
//            ctx.pipeline().addLast(new IdleStateHandler(60,0,0));
//            ctx.pipeline().addLast(new NettyHeartKeeper(NettyHeartKeeper.TYPE_TCP));
//            ctx.pipeline().addLast("lengthEncode",new LengthFieldPrepender(4, false));
//            ctx.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
//            ctx.pipeline().addLast(new MessageEncoder());

            // decoder 客户端 -> 服务端 解码
//            ctx.pipeline().addLast("lengthDecoder", new LengthFieldBasedFrameDecoder(1024 * 1024, 2, 2, 6, 10, false));
//            ctx.pipeline().addLast("lengthDecoder", new LengthFieldBasedFrameDecoder(ByteOrder.LITTLE_ENDIAN,1024*1024,0,4,0,4,false));
//            ctx.pipeline().addLast(new InstructionLengthFieldBasedFrameDecoder());
            ctx.pipeline().addLast("lengthDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
            ctx.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
            ctx.pipeline().addLast(new JsonStringHandler());

//            ctx.pipeline().addLast(new BytebufToByteHandler());
//            ctx.pipeline().addLast(new TcpSocketHandler());
        }
        in.resetReaderIndex();
        ctx.pipeline().remove(this.getClass());
    }

    private String getBufStart(ByteBuf in) {
        int length = in.readableBytes();
        // 标记读位置
        in.markReaderIndex();
        byte[] content = new byte[length];
        in.readBytes(content);
        return new String(content);
    }

    //    @Override
//    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
//        String protocol = getBufStart(in);
//        if (protocol.startsWith(WEBSOCKET_PREFIX)) {
//            ctx.pipeline().remove(LengthFieldBasedFrameDecoder.class);
//            ctx.pipeline().remove(LengthFieldPrepender.class);
//            ctx.pipeline().remove(BytebufToByteHandle.class);
//        }
//
//        in.resetReaderIndex();
//        ctx.pipeline().remove(this.getClass());
//    }
//
//
//    private String getBufStart(ByteBuf in){
//        int length = in.readableBytes();
//        if (length > MAX_LENGTH) {
//            length = MAX_LENGTH;
//        }
//
//        // 标记读位置
//        in.markReaderIndex();
//        byte[] content = new byte[length];
//        in.readBytes(content);
//        return new String(content);
//    }
//
    public void websocketAdd(ChannelHandlerContext ctx) {
        // HttpServerCodec：将请求和应答消息解码为HTTP消息
        ctx.pipeline().addBefore("byteToBuf", "http-codec", new HttpServerCodec());

        // HttpObjectAggregator：将HTTP消息的多个部分合成一条完整的HTTP消息
        ctx.pipeline().addBefore("byteToBuf", "aggregator", new HttpObjectAggregator(65535));

        // ChunkedWriteHandler：向客户端发送HTML5文件
        ctx.pipeline().addBefore("byteToBuf", "http-chunked", new ChunkedWriteHandler());

        ctx.pipeline().addBefore("byteToBuf", "WebSocketAggregator", new WebSocketFrameAggregator(65535));

//        // 在管道中添加我们自己的接收数据实现方法
//        ctx.pipeline().addBefore("byteToBuf","ws-handShake",wsHandShakeServerHandle);
//
//        // 后续直接走消息处理
//        ctx.pipeline().addBefore("byteToBuf","wsPack",wsPacketHandle);
//
//        // 编码。将通用byteBuf编码成binaryWebSocketFrame.通过前面的编码器
//        ctx.pipeline().addBefore("byteToBuf","bufToFrame",bytebufToBinaryFrameHandle);
    }
}
